enchant();

function d(r) {
    return r / Math.PI * 180;
}

function add(v1, v2) {
    return { x: v1.x + v2.x, y: v1.y + v2.y };
}
function sub(v1, v2) {
    return { x: v1.x - v2.x, y: v1.y - v2.y };
}
function angle(p1, p2) {
    var t = (p1.x != p2.x) ? Math.atan( (p2.y - p1.y) / (p2.x - p1.x) ) : Math.PI/2;
    if (p2.x - p1.x <= 0) t += Math.PI;
    return t;
}
function length(v) {
    return Math.sqrt(v.x * v.x + v.y * v.y);
}
function distance(p1, p2) {
    return Math.sqrt((p2.x-p1.x)*(p2.x-p1.x) + (p2.y-p1.y)*(p2.y-p1.y));
}

/**
 * line p1-p2
 *  and
 * point p
 */
function distanceLinePoint(lp1, lp2, p) {
    var p1p = distance(lp1, p);
    var p2p = distance(lp2, p);
    var p1p2 = distance(lp1, lp2);
    var x = p1p * p1p2 / (p1p+p2p);
    if (p1p < x) return 0.0;
    return Math.sqrt(p1p*p1p - x*x);
}

window.onload = function() {
    var game = new Game(320, 320);
    game.preload(["charge.png", "chara1.gif"]);
    game.rootScene.backgroundColor = "#000";

    game.onload = function() {
        var test = distanceLinePoint({x:0,y:0}, {x:100,y:0}, {x:50,y:100});
        console.log("test = " + test);
        console.log("test2 = " + distanceLinePoint({x:0,y:0}, {x:2,y:2}, {x:2,y:0}));
        console.log("test3 = " + distanceLinePoint({x:0,y:0}, {x:2,y:2}, {x:0,y:2}));
        console.log("test3 = " + distanceLinePoint({x:0,y:0}, {x:200,y:200}, {x:0,y:200}));
        console.log("test3 = " + distanceLinePoint({x:0,y:0}, {x:0,y:200}, {x:100,y:100}));
        
        var stage = new Group();
        game.rootScene.addChild(stage);

        var s = new Surface(320, 320);
        var beamLayer = s.context;

        var target = new Sprite(32, 32);
        target.image = game.assets["chara1.gif"];
        stage.addChild(target);
        beamLayer.beginPath();
        beamLayer.arc(target.x, target.y, 5, 0, Math.PI*2, true);
        beamLayer.fill();

        var acceleration = 12;
        var maxSpeed = 20;

        var test = new Entity();
        test.x = 30;
        test.y = 160;
        stage.addChild(test);

        var effect = new Sprite(32, 32);
        effect.image = game.assets["charge.png"];
        effect.frame = 31;
        effect.x = test.x - effect.width / 2;
        effect.y = test.y - effect.height / 2;
        effect.addEventListener("enterframe", function() {
            this.frame -= 1;
            if (this.frame < 0) this.frame = 31
        });
        stage.addChild(effect);

        stage.addEventListener("enterframe", function() {
            s.clear();

            beam(beamLayer, 10, 60, 10, 260);
            beam(beamLayer, 30, 260, 30, 60);
            beam(beamLayer, 60, 50, 260, 50);
            beam(beamLayer, 260, 80, 60, 80);
            beam(beamLayer, 100, 100, 260, 260);
            beam(beamLayer, 260, 100, 100, 260);
            beam(beamLayer, 280, 260, 120, 100);
            beam(beamLayer, 120, 260, 280, 100);

            beamLayer.fillStyle = "#f00";
            beamLayer.beginPath();
            beamLayer.arc(target.x + target.width / 2, target.y + target.height / 2, 3, Math.PI*2, false);
            beamLayer.fill();

            if (game.frame % 50 == 0) {
                target.x = Math.random() * 320;
                target.y = Math.random() * 320;
                for (var i = -3; i <= 3; i+=1) {
                    if (i == 0) continue;
            
                    var homingLazer = new Entity();
                    homingLazer.count = 0;
                    homingLazer.path = homingPath(test, {
                        x: Math.cos(i) * 20,
                        y: Math.sin(i) * 20
                    }, {
                        x: target.x + target.width / 2,
                        y: target.y + target.height / 2
                    }, acceleration, maxSpeed);
                    homingLazer.addEventListener("enterframe", function() {
                        this.count += 1;
                        if (this.path.length + 26 < this.count) {
                            stage.removeChild(this);
                        }
                        draw(beamLayer, this.path, this.count);
                    });
                    stage.addChild(homingLazer);
                }
            }

        });

        var e = new Sprite(320, 320);
        e.image = s;
        e.x = 0;
        e.y = 0;
        stage.addChild(e);
    };
    game.start();
};

function homingPath(initialPosition, initialVelocity, targetPosition, acceleration, maxSpeed, minSpeed) {
    var posotion = initialPosition;
    var velocity = initialVelocity;
    if (!minSpeed) {
        var minSpeed = 8;
    }

    var path = [ posotion ];
    var count = 0;
    var accel = acceleration;
    while (0 < posotion.x && posotion.x < 320 && 0 < posotion.y && posotion.y < 320) {
        var a = angle(posotion, targetPosition);
        
        if (count < acceleration) {
            velocity = add(velocity, {
                x: Math.cos(a) * accel,
                y: Math.sin(a) * accel
            });
        }
        var speed = length(velocity);
        if (speed == 0) return path;
        if (maxSpeed < speed) {
            velocity.x *= maxSpeed/speed;
            velocity.y *= maxSpeed/speed;
        } else if (speed < minSpeed) {
            velocity.x *= minSpeed/speed;
            velocity.y *= minSpeed/speed;
        }

        posotion = add(posotion, velocity);
        path.push(posotion);
        count += 1;
        accel = accel > 0 ? accel - 0.5 : 0;
    }
    return path;
}

function beam(context, x1, y1, x2, y2) {
    line(context, x1, y1, x2, y2, 6, "rgb(  0,   0, 255)");
    line(context, x1, y1, x2, y2, 5, "rgb(128, 128, 255)");
    line(context, x1, y1, x2, y2, 4, "rgb(255, 255, 255)");
}

function line(context, x1, y1, x2, y2, w, color) {
    context.fillStyle = color;

    var t = (x1!=x2) ? Math.atan( (y2-y1) / (x2-x1) ) : Math.PI/2;
    if (x2 < x1) {
        if (y2 < y1) {
            t += Math.PI;
        } else {
            t -= Math.PI;
        }
    }

    var t1 = t + Math.PI/2;
    var t2 = t - Math.PI/2;

    context.beginPath();
    context.moveTo(x1 + Math.cos(t1)*w, y1 + Math.sin(t1)*w);
    context.lineTo(x2 + Math.cos(t1)*w, y2 + Math.sin(t1)*w);
    context.lineTo(x2 + Math.cos(t)*w, y2 + Math.sin(t)*w);
    context.lineTo(x2 + Math.cos(t2)*w, y2 + Math.sin(t2)*w);
    context.lineTo(x1 + Math.cos(t2)*w, y1 + Math.sin(t2)*w);
    context.lineTo(x1 - Math.cos(t)*w, y1 - Math.sin(t)*w);
    context.closePath();
    context.fill();
}

function draw(context, path, count) {
    if (path.length <= 1) return;
    if (count <= 1) return;
    var c = 256;
    var w = 3;
    for (var i = count; i >= 1; i--) {
        c -= 10;
        w -= 0.2;
        if (i < path.length && 0 < c && 0 < w) {
            line(context, path[i-1].x, path[i-1].y, path[i].x, path[i].y, w, "rgba("+c+","+c+","+c+","+c/256+")");
        }
    }
}
